#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>

#define N 128

int main(int argc, char const *argv[])
{
    //创建一个管道
    int fd_send[2];
    int fd_recv[2];
    char buf[N] = {0};
    int ret = pipe(fd_send);
    if (ret < 0)
    {
        perror("pipe");
        exit(-1);
    }
    ret = pipe(fd_recv);
    if (ret < 0)
    {
        perror("pipe");
        exit(-1);
    }

    printf("fd_send[0]=%d\n", fd_send[0]); //读端
    printf("fd_send[1]=%d\n", fd_send[1]); //写端
    printf("fd_recv[0]=%d\n", fd_recv[0]); //读端
    printf("fd_recv[1]=%d\n", fd_recv[1]); //写端

    // fork 后，因为管道被创建在内核中，并不会创建克隆
     // 但是 fd_send[0] 会变成2个 , fd_send[1] 也会变成2个 , 把多余fd_send[0]和fd_send[1]关闭
    // 但是 fd_recv[0] 会变成2个 , fd_recv[1] 也会变成2个 , 把多余fd_recv[0]和fd_recv[1]关闭
    pid_t pid = fork(); //错误
    if (pid < 0)
    {
        perror("fork");
        exit(-1);
    }
    else if (pid == 0) //表示的是子进程
    {
        close(fd_send[0]);                    //关闭接收端
        close(fd_recv[1]);                    //关闭发送端
        printf("child: pid=%d\n", getpid());  //获取当进程的进程号
        printf("child: pid=%d\n", getppid()); //获取父进程的进程号

        while (1)
        {
            printf("child >:");
            fgets(buf, N, stdin);     // 从终端读数据
            buf[strlen(buf) - 1] = 0; //消除最后一个字符，即可清除'\n'
            ret = write(fd_send[1], buf, N);
            if (ret < 0)
            {
                perror("write");
                exit(-1);
            }
            if (strncmp(buf, "quit", 4) == 0)
                break; // 用户输入quit后退出程序
            memset(buf, 0, N);
            ret = read(fd_recv[0], buf, N);
            if (ret < 0)
            {
                perror("write");
                exit(-1);
            }
            if (strncmp(buf, "quit", 4) == 0)
                break; // 用户输入quit后退出程序
            printf("child: readfrom parent:%s\n", buf);
        }
    }
    else //表示父进程 pid>0
    {
        close(fd_send[1]);                     //关闭发送端
        close(fd_recv[0]);                     //关闭发送端
        printf("parent: pid=%d\n", getpid());  //获取当进程的进程号
        printf("parent: pid=%d\n", getppid()); //获取父进程的进程号

        while (1)
        {
            ret = read(fd_send[0], buf, N);
            if (ret < 0)
            {
                perror("read");
                exit(-1);
            }
            if (strncmp(buf, "quit", 4) == 0)
                break; // 用户输入quit后退出程序
            printf("parent: readfrom child:%s\n", buf);
            printf("parent >:");
            fgets(buf, N, stdin);     // 从终端读数据
            buf[strlen(buf) - 1] = 0; //消除最后一个字符，即可清除'\n'
            ret = write(fd_recv[1], buf, N);
            if (ret < 0)
            {
                perror("write");
                exit(-1);
            }
            if (strncmp(buf, "quit", 4) == 0)
                break; // 用户输入quit后退出程序
            memset(buf, 0, N);
        }
    }
    return 0;
}
